package com.geotmt.billingcenter.modules.cost.service.impl;

import com.geotmt.billingcenter.common.entry.CostBaseEntry;
import com.geotmt.billingcenter.common.entry.CostRuleEntry;
import com.geotmt.billingcenter.common.entry.CostRuleHisEntry;
import com.geotmt.billingcenter.common.entry.StairRule;
import com.geotmt.billingcenter.common.enumpackage.CostFeeFlagEnum;
import com.geotmt.billingcenter.common.enumpackage.RuleLabelEnum;
import com.geotmt.billingcenter.common.exception.MyException;
import com.geotmt.billingcenter.common.utils.GeoDateUtils;
import com.geotmt.billingcenter.common.vo.cost.CostHisVo;
import com.geotmt.billingcenter.common.vo.cost.CostVo;
import com.geotmt.billingcenter.common.vo.params.PageOrgFilter;
import com.geotmt.billingcenter.common.vo.params.ParamsCost;
import com.geotmt.billingcenter.common.vo.params.ParamsForDel;
import com.geotmt.billingcenter.modules.cost.service.*;
import com.geotmt.billingcenter.modules.rules.service.RulesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @Description 成本
 * @Author      yanghanwei
 * @Mail        yanghanwei@geotmt.com
 * @Date        2019/3/19 20:30
 * @Version     v1
 **/
@Service
@Transactional(rollbackFor = Exception.class)
public class CostServiceImpl extends PageOrgFilter implements CostService {

    private static final Logger logger = LoggerFactory.getLogger(CostServiceImpl.class);

    /**
     * 没有记录需要新增
     */
    private static final String NEW_LIST = "newList";

    /**
     * 有记录但是未生效
     */
    private static final String INVALID_LIST = "invalidList";

    /**
     * 有记录并且已经生效
     */
    private static final String EFFECT_LIST = "effectList";

    /**
     * 不符合添加条件的
     */
    private static final String NOT_FIT_LIST = "notFitList";

    @Resource
    private CostBaseService costBaseService;

    @Resource
    private CostRuleService costRuleService;

    @Resource
    private CostBaseHisService costBaseHisService;

    @Resource
    private CostRuleHisService costRuleHisService;

    @Resource
    private RulesService rulesService;

    @Override
    public void addList(List<CostVo> costList) throws Exception {
        logger.info("成本组合 add service");
        if(null != costList && !costList.isEmpty()){
            for(CostVo costVo : costList){
                // 添加 有记录已生效的规则(包含新规则)
                this.addEffectRule(costVo);
            }
        }
    }

    @Override
    public void addUpdateList(List<CostVo> consumeVoList, HttpServletRequest request) throws Exception {
        logger.info("添加或更新成本规则");
        Map<String, Object> resultMap = this.analyzeList(consumeVoList);
        List<CostVo> newList = (List<CostVo>)resultMap.get(NEW_LIST);
        List<CostVo> invalidList = (List<CostVo>)resultMap.get(INVALID_LIST);
        List<CostVo> effectList = (List<CostVo>)resultMap.get(EFFECT_LIST);
        Integer userId = this.getUserId(request);
        //保存没有记录需要新增的
        if(null != newList && !newList.isEmpty()){
            logger.info("保存没有记录需要新增的，newList：{}",newList);
            for(CostVo vo : newList){
                vo.setCreateTime(new Date());
                vo.setCreateUserId(userId);
                this.addNewRuleSign(vo);
            }
        }
        //修改有记录但未生效的
        if(null != invalidList && !invalidList.isEmpty()){
            logger.info("修改有记录但未生效的，invalidList：{}",invalidList);
            for(CostVo vo : invalidList){
                vo.setUpdateTime(new Date());
                vo.setUpdateUserId(userId);
                this.update(vo);
            }
        }
        //覆盖有记录并且已生效的
        if(null != effectList && !effectList.isEmpty()){
            logger.info("覆盖有记录并且已生效的，effectList：{}",effectList);
            for(CostVo vo : effectList){
                vo.setCreateTime(new Date());
                vo.setCreateUserId(userId);
                this.addEffectRule(vo);
            }
        }

    }

    @Override
    public Map<String, Object> analyzeList(List<CostVo> costList) {
        Map<String,Object> resultMap = new HashMap<>(3);
        List<CostVo> newList = new ArrayList<>();
        List<CostVo> invalidList = new ArrayList<>();
        List<CostVo> effectList = new ArrayList<>();
        List<CostVo> notFitList = new ArrayList<>();
        for(CostVo costVo : costList){
            ParamsCost params = new ParamsCost(costVo.getDsId(), costVo.getOutInterfaceId());
            //得到的结果最多只有一个
            List<CostVo> costVoList = costBaseService.listCurr(params);
            if(null != costVoList && !costVoList.isEmpty() && costVoList.size() == 1){
                for(CostVo vo : costVoList){
                    if(GeoDateUtils.getLongDate(vo.getEffectTime()) - GeoDateUtils.getLongDate(new Date()) >= 0){
                        //有记录但是未生效
                        invalidList.add(costVo);
                    }else{
                        //有记录并且已经生效
                        effectList.add(costVo);
                    }
                }
            }else{
                //没有记录需要新增
                if(null != costVo.getFeeFlag() && null != costVo.getEffectTime()){
                    newList.add(costVo);
                }else {
                    notFitList.add(costVo);
                }
            }
        }
        resultMap.put(NEW_LIST,newList);
        resultMap.put(INVALID_LIST,invalidList);
        resultMap.put(EFFECT_LIST,effectList);
        resultMap.put(NOT_FIT_LIST,notFitList);
        return resultMap;
    }

    @Override
    public void update(CostVo costVo) throws Exception {
        logger.info("成本组合 update service");
        //0.查询当前记录 是否 已经生效
        CostVo con = costBaseService.currGetById(costVo.getId());
        long dateYes= System.currentTimeMillis() - 1000L * 60 * 60 * 24;
        if(null != con && GeoDateUtils.getLongDate(con.getEffectTime()) <= GeoDateUtils.getLongDate(new Date(dateYes))){
            throw new MyException("此规则已经生效，不支持修改，请移步至历史规则", HttpServletResponse.SC_NOT_ACCEPTABLE);
        }
        //1.更新curr 中的记录
        CostRuleEntry costRule = new CostRuleEntry();
        BeanUtils.copyProperties(costVo,costRule);
        Integer id = costRuleService.addRule(costRule);
        if(null != id){
            //2.1 保存阶梯规则
            this.addStairRule(costVo,id);
            //2.2 更新 consume 中的记录
            if(null == costVo.getUpdateTime()){
                costVo.setUpdateTime(new Date());
            }
            costVo.setRId(id);
            costBaseService.updateBase(costVo);
            //更新历史表中有效结束时间
            ParamsCost params = new ParamsCost();
            BeanUtils.copyProperties(costVo,params);
            List<CostHisVo> costHisVos = costBaseHisService.listHis(params);
            if(null != costHisVos && !costHisVos.isEmpty()) {
                costBaseHisService.updateEndEffect(GeoDateUtils.getPreDay(costVo.getEffectTime(),-1),costHisVos.get(0).getId());
            }
        }
    }

    @Override
    public void delete(ParamsForDel obj) throws Exception {
        logger.info("消耗组合 delete service");
        CostVo con = costBaseService.currGetById(obj.getId());
        long dateYes= System.currentTimeMillis() - 1000L * 60 * 60 * 24;
        if(null != con && GeoDateUtils.getLongDate(con.getEffectTime()) <= GeoDateUtils.getLongDate(new Date(dateYes))){
            throw new MyException("此规则已经生效，不能删除!", HttpServletResponse.SC_NOT_ACCEPTABLE);
        }
        if(null == obj.getUpdateTime()){
            obj.setUpdateTime(new Date());
        }
        costBaseService.deleteBase(obj);
    }

    @Override
    public List<CostVo> list(ParamsCost obj) {
        logger.info("成本 list curr");
        return costBaseService.listCurr(obj);
    }

    @Override
    public List<CostVo> listAll(ParamsCost obj) {
        logger.info("添加或修改的回显 curr");
        return costBaseService.listAll(obj);
    }

    @Override
    public List<CostHisVo> listHis(ParamsCost obj) {
        logger.info("成本 list his");
        return costBaseHisService.listHis(obj);
    }

    @Override
    public CostHisVo getCost(int dsId, int outInterfaceId, Date date) {
        logger.info("获取当前有效的规则 service");
        String dateDay;
        if(null == date){
            date = new Date();
        }
        dateDay = GeoDateUtils.dateStr(date, GeoDateUtils.DATE_FORMAT);
        return costBaseService.getCost(dsId,outInterfaceId, dateDay);
    }


    /**
     * 保存阶梯规则
     * @param costVo
     * @param rId
     */
    private void addStairRule(CostVo costVo, Integer rId) throws Exception{
        if(CostFeeFlagEnum.STAIR.value.equals(costVo.getFeeFlag())){
            List<StairRule> stairRuleList = costVo.getStairRuleList();
            if(null == stairRuleList){
                throw new MyException("阶梯计费详细规则不能为空！", HttpServletResponse.SC_NOT_ACCEPTABLE);
            }
            for(StairRule stairRule : stairRuleList){
                stairRule.setRId(rId);
                stairRule.setLabel(RuleLabelEnum.COST_CURR.value);
                rulesService.addStair(stairRule);
            }
        }
    }

    /**
     * 保存阶梯规则
     * @param costHisVo
     * @param rId
     * @throws Exception
     */
    private void addStairRule(CostHisVo costHisVo, Integer rId) throws Exception{
        if(CostFeeFlagEnum.STAIR.value.equals(costHisVo.getFeeFlag())){
            List<StairRule> stairRuleList = costHisVo.getStairRuleList();
            if(null == stairRuleList){
                throw new MyException("阶梯计费 详细规则不能为空！", HttpServletResponse.SC_NOT_ACCEPTABLE);
            }
            for(StairRule stairRule : stairRuleList){
                stairRule.setRId(rId);
                stairRule.setLabel(RuleLabelEnum.COST_HIS.value);
                rulesService.addStair(stairRule);
            }
        }
    }

    /**
     * 保存 没有记录的规则
     * @param costVo
     * @throws Exception
     */
    private void addNewRuleSign(CostVo costVo) throws Exception{
        CostRuleEntry costRule = new CostRuleEntry();
        BeanUtils.copyProperties(costVo,costRule);
        Integer id = costRuleService.addRule(costRule);
        if(null != id){
            CostBaseEntry costBase = new CostBaseEntry();
            BeanUtils.copyProperties(costVo,costBase);
            costBase.setRId(id);
            costBaseService.addBase(costBase);
            //保存阶梯计费规则
            this.addStairRule(costVo, id);
        }
    }

    /**
     * 覆盖已有记录的规则
     * @param costVo
     * @throws Exception
     */
    private void addEffectRule(CostVo costVo) throws Exception{
        ParamsCost params = new ParamsCost(costVo.getDsId(), costVo.getOutInterfaceId());
        List<CostVo> costVoList = costBaseService.listCurr(params);
        if(null != costVoList && !costVoList.isEmpty()){

            //2.1 有记录就调用删除,并将本记录添加到 His 中
            for(CostVo costVo1 : costVoList){
                long dateYes= System.currentTimeMillis() - 1000L * 60 * 60 * 24;
                //如果未生效的 规则
                if(GeoDateUtils.getLongDate(costVo1.getEffectTime()) > GeoDateUtils.getLongDate(new Date(dateYes))){
                    throw new MyException("已经有未生效的配置，如需更新请点击更新操作！", HttpServletResponse.SC_NOT_ACCEPTABLE);
                }
                //2.1.1 delete base
                ParamsForDel params1 = new ParamsForDel(costVo1.getId(),costVo1.getCreateUserId(),new Date());
                costBaseService.deleteBase(params1);
                //2.1.2 add hisRule
                CostRuleHisEntry costRuleHis = new CostRuleHisEntry();
                BeanUtils.copyProperties(costVo1,costRuleHis);
                Integer id = costRuleHisService.addRuleHis(costRuleHis);
                if(id > 0){
                    //2.1.3 add hisBase
                    CostHisVo costHis = new CostHisVo();
                    BeanUtils.copyProperties(costVo1,costHis);
                    costHis.setEffectStartTime(costVo1.getEffectTime());
                    costHis.setEffectEndTime(GeoDateUtils.getDate(costVo.getEffectTime(), -1));
                    costHis.setUpdateUserId(costVo1.getCreateUserId());
                    if(null == costHis.getCreateTime()){
                        costHis.setCreateTime(new Date());
                    }
                    costHis.setRId(id);
                    costBaseHisService.addBaseHis(costHis);
                    //2.1.4 add stairRules
                    this.addStairRule(costHis,id);
                }
            }
            // 3 添加新规则
            this.addNewRuleSign(costVo);
        }
    }
}
